﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace SOEN341_SCHEDULER_PHASE1
{
    public partial class ui_form_StudentPage : Form
    {
        bool showingConstraints = false;
        static Font tableDefaultFont = new Font(FontFamily.GenericSansSerif, 2);

        TableGridPublicStaticMethods tgbs;

        List<Course>[] generatedResult;
        int resultCounter = 0;

        bool isFormDragged = false;
        int formMoveXOffset = 0;
        int formMoveYOffset = 0;

        public static bool changeMade;
        bool isBig = false;

        TimeTableBlock prevTtbForColor;
        Color prevColor;

        int prevTableWidth;
        int prevTableHeight;
        int prevFormWidth;
        int prevFormHeight;

        int cntr_sch = 0;

        Student currentUser;

        public ui_form_StudentPage()
        {
            InitializeComponent();
        }

        private void ui_form_student_page_Load(object sender, EventArgs e)
        {          
            currentUser = SetCurrentUser();

            InitVars();
            SetDefaultVariablesTableLayoutPanel();
            InitFormControls();
            SetEditPanelVisibility(false);

            GlobalVariablesClass.originalStudentPageWidth = this.Width;

            if (currentUser != null)
            {
                LoadStudentSchedule(currentUser);
                LoadStudentCourses(currentUser, ui_check_showTimes.Checked,true);               
                LoadProgramCourses(currentUser.GetProgram(), null, false, ui_check_showTimes.Checked);
            }
            tgbs.RefreshTtbGridColors();
            
        }

        private void SetEditPanelVisibility(bool isVisible)
        {
            ui_panel_edit.Visible = isVisible;
            if (!isVisible)
            {
                this.Width = ui_panel_edit.Left;
                
            }
            else
            {
                this.Width = ui_panel_edit.Left + ui_panel_edit.Width;
            }
        }

        private void InitVars()
        {
            

            tgbs = new TableGridPublicStaticMethods();
            GlobalVariablesClass.courseSelected = new List<Course>();
            changeMade = false;
        }

        private Student SetCurrentUser()
        {
            Student theStudent = GlobalVariablesClass.session_loggedInStudent;

            ui_toolStrip_lbl_User.Visible = true;
            ui_toolStrip_lbl_User.Dock = DockStyle.Left;
            ui_toolStrip_lbl_User.Text = theStudent.GetFirstName() + " " + theStudent.GetLastName();
            ui_toolStrip_lbl_User.Alignment = ToolStripItemAlignment.Right;

            ui_toolStrip_dropDown.Alignment = ToolStripItemAlignment.Right;
            ui_toolStrip_dropDown.Image = Properties.Resources.User_icon;
            
            return theStudent;
        }

        private void LoadProgramCourses(EducationalProgram ep, List<Course> progToSee, bool checkCollisions, bool showTime)
        {
            Course theTutorial;
            Course theLab;
            ui_list_inGb_courseMissing.Items.Clear();
            if (progToSee == null)
            {
                List<Course> listCourse = ep.GetAllCourses();
                Course[] arrCourse = listCourse.ToArray();
                if (arrCourse.Length > 0)
                {
                    for (int i = 0; i < arrCourse.Length; i++)
                    {
                        if (!showTime)
                        {
                            ui_list_inGb_courseMissing.DisplayMember = "CourseNameProperty";
                        }
                        else
                        {
                            ui_list_inGb_courseMissing.DisplayMember = "ToString";
                        }

                        if (showTime || !(IsCollide(ui_list_inGb_courseMissing, arrCourse[i])))
                        {
                            ui_list_inGb_courseMissing.Items.Add(arrCourse[i]);
                            theTutorial = arrCourse[i].GetTutorial();
                            theLab = arrCourse[i].GetLab();

                            if (theTutorial != null)
                            {
                                ui_list_inGb_courseMissing.Items.Add(theTutorial);
                            }
                            if (theLab != null)
                            {
                                ui_list_inGb_courseMissing.Items.Add(theLab);
                            }


                            Object[] toTag = new Object[2];
                            toTag[0] = theTutorial;
                            toTag[1] = theLab;

                            arrCourse[i].Tag = toTag;
                        }
                    }
                }
            }
            else
            {
                List<Course> studentCourses = progToSee;
                Course[] arrStudentCourse = studentCourses.ToArray();
                List<Course> eduCourse = ep.GetAllCourses();
                Course[] arrEduCourse = eduCourse.ToArray();
                bool isFound = false;
                for (int i = 0; i < arrEduCourse.Length; i++)
                {
                    if (!showTime)
                    {
                        ui_list_inGb_courseMissing.DisplayMember = "CourseNameProperty";
                    }
                    else
                    {
                        ui_list_inGb_courseMissing.DisplayMember = "ToString";
                    }

                    isFound = false;
                    for (int k = 0; k < arrStudentCourse.Length; k++)
                    {

                        if (arrStudentCourse[k].IsSameClassName(arrEduCourse[i]))
                        {
                            isFound = true;
                            break;
                        }
                    }
                    if (!isFound)
                    {
                        theTutorial = arrEduCourse[i].GetTutorial();
                        theLab = arrEduCourse[i].GetLab();

                        if (!checkCollisions || (!tgbs.CheckCollision(arrEduCourse[i]) &&
                            !tgbs.CheckCollision(theTutorial) &&
                            !tgbs.CheckCollision(theLab)))
                        {
                            if (showTime || !(IsCollide(ui_list_inGb_courseMissing, arrEduCourse[i])))
                            {
                                ui_list_inGb_courseMissing.Items.Add(arrEduCourse[i]);

                                if (theTutorial != null)
                                {
                                    ui_list_inGb_courseMissing.Items.Add(theTutorial);
                                }
                                if (theLab != null)
                                {
                                    ui_list_inGb_courseMissing.Items.Add(theLab);
                                }


                                Object[] toTag = new Object[2];
                                toTag[0] = theTutorial;
                                toTag[1] = theLab;

                                arrEduCourse[i].Tag = toTag;
                            }
                        }
                        else
                        {
                            ui_status_lbl.Text = "Some courses are in conflict with your schedule...";
                            ui_status_lbl.ForeColor = Color.Red;
                        }
                    }
                }
            }
        }

        private bool CourseNameExist(ListBox listCheck, Course cs)
        {
            Course toComp;

            for (int i = 0; i < listCheck.Items.Count; i++)
            {
                toComp = (Course)listCheck.Items[i];

                if (toComp.GetCourseName().Equals(cs.GetCourseName()))
                {
                    return true;
                }
            }
            return false;
        }

        private void LoadStudentCourses(Student std, bool showTime, bool loadReg)
        {
            List<Course> listCourses = std.GetCurrentCourses();
            Course[] arrCourses;
            if (loadReg)
            {
                arrCourses = listCourses.ToArray();
            }
            else
            {
                arrCourses = GlobalVariablesClass.courseSelected.ToArray();
            }

            Course theTutorial;
            Course theLab;
            ui_list_inGb_currCourses.Items.Clear();
            if (!showTime)
            {
                ui_list_inGb_currCourses.DisplayMember = "CourseNameProperty";
            }
            else
            {
                ui_list_inGb_currCourses.DisplayMember = "ToString";
            }

            if (arrCourses.Length > 0)
            {
                for (int i = 0; i < arrCourses.Length; i++)
                {
                    ui_list_inGb_currCourses.Items.Add(arrCourses[i]);
                    
                    theTutorial = arrCourses[i].GetTutorial();
                    theLab = arrCourses[i].GetLab();
                    if (theTutorial != null)
                    {
                        ui_list_inGb_currCourses.Items.Add(theTutorial);
                    }
                    if (theLab != null)
                    {
                        ui_list_inGb_currCourses.Items.Add(theLab);
                    }
                    if (loadReg)
                    {
                        GlobalVariablesClass.courseSelected.Add(arrCourses[i]);
                    }

                    Object[] toTag = new Object[2];
                    toTag[0] = theTutorial;
                    toTag[1] = theLab;
                    arrCourses[i].Tag = toTag;
                }
            }
            else
            {
                ui_list_inGb_currCourses.Tag = -1;
                ui_list_inGb_currCourses.Items.Add("Not registered to any courses");
            }
        }

        private Student GetSessionCurrentStudent()
        {
            return GlobalVariablesClass.session_loggedInStudent;
        }

        private void SetDefaultVariablesTableLayoutPanel()
        {

            tgbs.defaultTableGrid = ui_tableLayout;
        }

        private void InitFormControls()
        {
            Top = GlobalVariablesClass.LocationMainY;
            Left = GlobalVariablesClass.LocationMainX;

            tgbs.TableGridInitializeGenerateDefaultLabels(tableDefaultFont);

            ui_gb_Course_List.Text = "Course list (" + currentUser.GetProgramName() + ")";
        }

        private bool LoadStudentSchedule(Student studentToDisplay)
        {
            return tgbs.GenerateStudentSchedule(studentToDisplay);
        }

        private void ui_list_inGb_currCourses_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (prevTtbForColor != null)
            {
                prevTtbForColor.SetBlocColor(prevColor);
            }
            if (ui_list_inGb_currCourses.Tag==null)
            {
                ListBox theListBox = (ListBox)sender;
                int currIndex = theListBox.SelectedIndex;
                
                if (currIndex != -1)
                {
                    try
                    {
                        Course theCourse = (Course)theListBox.Items[currIndex];
                        TimeTableBlock ttb = theCourse.GetTimeTableBlock();

                        prevTtbForColor = ttb;
                        prevColor = ttb.GetBlocColor();

                        ttb.SetBlocColor(Color.Fuchsia);

                        tgbs.RefreshTtbGridColors();
                    }
                    catch (Exception) { }
                }
            }

        }

        private void ui_form_student_page_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (changeMade)
            {
                DialogResult = MessageBox.Show("Do you want to save", "Save", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (DialogResult == DialogResult.Yes)
                {
                    SaveSession();
                }
            }
            GlobalVariablesClass.ui_main_form_login.Show();
        }

        private void logOutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LogOut();
        }

        private void LogOut()
        {
            if (prevTtbForColor != null)
            {
                prevTtbForColor.SetBlocColor(prevColor);
            }
            //ask to save
            if (changeMade)
            {
                changeMade = false;
                DialogResult = MessageBox.Show("Do you want to save?", "Save", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (DialogResult == DialogResult.Yes)
                {
                    SaveSession();
                }
            }

            this.Close();
        }

        private void SaveSession()
        {

            if (prevTtbForColor != null)
            {
                prevTtbForColor.SetBlocColor(prevColor);
            }

            //save
            GlobalVariablesClass.session_loggedInStudent.SetAllCourses(GlobalVariablesClass.courseSelected);
            Student[] arrStud = GlobalVariablesClass.list_RegisteredStudents.ToArray();

            Stream stream = null;
            try
            {
                stream = File.Open(GlobalVariablesClass.file_StudentRegistered, FileMode.OpenOrCreate);
                BinaryFormatter bf = new BinaryFormatter();
                for (int i = 0; i < arrStud.Length; i++)
                {
                    bf.Serialize(stream, arrStud[i]);
                }
            }
            catch (FileNotFoundException)
            {
                GlobalVariablesClass.LogError("Could not find student file [" +
                    GlobalVariablesClass.file_StudentRegistered + "]");
            }
            catch (Exception f)
            {
                if (stream != null) stream.Close();
                GlobalVariablesClass.LogError("Error while saving student file: " + f.Message);
            }

            changeMade = false;
        }

        private void ui_toolStrip_dropDown_ButtonClick(object sender, EventArgs e)
        {
            ui_toolStrip_dropDown.ShowDropDown();
        }

        private void ui_link_inGb_edit_courses_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (ui_link_inGb_edit_courses.Tag == null)
            {
                ui_link_inGb_edit_courses.Tag = 0;
            }

            if (((int)ui_link_inGb_edit_courses.Tag) == 0)
            {
                ui_link_inGb_edit_courses.Tag = 1;
                ui_link_inGb_edit_courses.Text = "Hide";
                SetEditPanelVisibility(true);
            }
            else
            {
                ui_link_inGb_edit_courses.Text = "Edit";
                ui_link_inGb_edit_courses.Tag = 0;
                SetEditPanelVisibility(false);
            }
        }

        private void ui_link_edit_hide_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            SetEditPanelVisibility(false);
            ui_link_inGb_edit_courses.Text = "Edit";
            ui_link_inGb_edit_courses.Tag = 0;
        }

        private void ui_btn_inGb_Add_Click(object sender, EventArgs e)
        {
            int indexSelected = ui_list_inGb_courseMissing.SelectedIndex;
            Course theCourse;
            changeMade = true;
            Course theTutorial;
            Course theLab;
            if (indexSelected != -1)
            {
                try
                {
                    theCourse = (Course)ui_list_inGb_courseMissing.SelectedItem;
                    theLab = theCourse.GetLab();
                    theTutorial = theCourse.GetTutorial();
                    //check Collisions
                    if (!IsCollide(ui_list_inGb_currCourses,theCourse) && !theCourse.IsTutorialOrLab())
                    {
                        //check collisions on form
                        if (!tgbs.CheckCollision(theCourse) && !tgbs.CheckCollision(theLab)
                            && !tgbs.CheckCollision(theTutorial))
                        {
                            if (ui_list_inGb_currCourses.Tag != null)
                            {
                                ui_list_inGb_currCourses.Items.Clear();
                            }
                            ui_list_inGb_currCourses.Tag = null;

                            Object[] theTags = (Object[])theCourse.Tag;

                            ui_list_inGb_courseMissing.Items.Remove(theCourse);
                            ui_list_inGb_currCourses.Items.Add(theCourse);

                            for (int i = 0; i < theTags.Length; i++)
                            {
                                if (theTags[i] != null)
                                {
                                    ui_list_inGb_currCourses.Items.Add(theTags[i]);
                                    ui_list_inGb_courseMissing.Items.Remove(theTags[i]);
                                }
                            }

                            RemoveDuplicate(ui_list_inGb_courseMissing, theCourse);

                            GlobalVariablesClass.courseSelected.Add(theCourse);

                            ui_status_lbl.Text = "Course Added";
                            ui_status_lbl.ForeColor = Color.Green;
                            RefreshGrid();
                            changeMade = true;

                            EducationalProgram ep = GlobalVariablesClass.session_loggedInStudent.GetProgram();

                            if (ui_check_missing.Checked)
                            {
                                LoadProgramCourses(ep, GlobalVariablesClass.courseSelected, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
                            }
                            else
                            {
                                LoadProgramCourses(currentUser.GetProgram(), null, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
                            }
                            
                        }
                        else
                        {
                            ui_status_lbl.Text = "Could not add [" + theCourse.ToString() + "] :: Collision detected";
                            ui_status_lbl.ForeColor = Color.Red;
                        }
                    }
                    else
                    {
                        if (theCourse.IsTutorialOrLab())
                        {
                            ui_status_lbl.Text = "Please select a class group";
                            ui_status_lbl.ForeColor = Color.Red;
                        }
                        else
                        {
                            ui_status_lbl.Text = "Courses already added!";
                            ui_status_lbl.ForeColor = Color.Red;
                        }
                    }
                }
                catch (Exception)
                {
                    ui_status_lbl.Text = "Please select a class group";
                    ui_status_lbl.ForeColor = Color.Red;
                }
            }
            
        }

        void RemoveDuplicate(ListBox theList, Course cs)
        {
            Course toComp;
            Course theTutorial;
            Course theLab;
            List<Course> toReAdd = new List<Course>();


            for (int i = 0; i < theList.Items.Count; i++)
            {
                toComp = (Course)theList.Items[i];
                if (!toComp.GetCourseName().Equals(cs.GetCourseName()) && !toComp.IsTutorialOrLab())
                {
                    toReAdd.Add(toComp);
                }
            }
            ui_list_inGb_courseMissing.Items.Clear();

            Course[] arrToAdd = toReAdd.ToArray();

            for (int i = 0; i < arrToAdd.Length; i++)
            {
                theTutorial = arrToAdd[i].GetTutorial();
                theLab = arrToAdd[i].GetLab();

                ui_list_inGb_courseMissing.Items.Add(arrToAdd[i]);

                if (theTutorial != null)
                {
                    ui_list_inGb_courseMissing.Items.Add(theTutorial);
                }
                if (theLab!=null)
                {
                    ui_list_inGb_courseMissing.Items.Add(theLab);
                }
            }
        }

        private void ui_btn_inGb_Remove_Click(object sender, EventArgs e)
        {
            int indexSelected = ui_list_inGb_currCourses.SelectedIndex;
            Course theCourse;
            changeMade = true;

            if (ui_list_inGb_currCourses.Tag==null &&  indexSelected != -1)
            {
                try
                {
                    theCourse = (Course)ui_list_inGb_currCourses.SelectedItem;
                    if (!theCourse.IsTutorialOrLab())
                    {
                        //get tags
                        Object[] theTags = (Object[])theCourse.Tag;

                        ui_list_inGb_currCourses.Items.Remove(theCourse);
                        ui_list_inGb_courseMissing.Items.Add(theCourse);

                        for (int i = 0; i < theTags.Length; i++)
                        {
                            if (theTags[i] != null)
                            {
                                ui_list_inGb_currCourses.Items.Remove(theTags[i]);
                                ui_list_inGb_courseMissing.Items.Add(theTags[i]);
                            }
                        }

                        GlobalVariablesClass.courseSelected.Remove(theCourse);

                        ui_status_lbl.Text = "Course removed";
                        ui_status_lbl.ForeColor = Color.Green;
                        
                        
                        RefreshGrid();

                        EducationalProgram ep = GlobalVariablesClass.session_loggedInStudent.GetProgram();

                        if (ui_check_missing.Checked)
                        {
                            LoadProgramCourses(ep, GlobalVariablesClass.courseSelected, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
                        }
                        else
                        {
                            LoadProgramCourses(currentUser.GetProgram(), null, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
                        }
                    }
                    else
                    {
                        ui_status_lbl.Text = "Please select a class group";
                        ui_status_lbl.ForeColor = Color.Red;
                    }
                }
                catch (Exception)
                {
                    ui_status_lbl.Text = "Please select a class group";
                    ui_status_lbl.ForeColor = Color.Red;
                }
            }
            
        }

        private void ReAddAllCourses(ListBox theList, Course cs)
        {
            Student theStudent = GlobalVariablesClass.session_loggedInStudent;
            EducationalProgram edu = theStudent.GetProgram();
            List<Course> eduCourses = edu.GetAllCourses();
            Course[] arrEduCourses = eduCourses.ToArray();

            Course theTutorial;
            Course theLab;

            //check collisions

            for (int i = 0; i < arrEduCourses.Length; i++)
            {
                theTutorial = arrEduCourses[i].GetTutorial();
                theLab = arrEduCourses[i].GetLab();

                if (arrEduCourses[i].IsSameClassName(cs) && !cs.Equals(arrEduCourses[i]))
                {
                        theList.Items.Add(arrEduCourses[i]);
                        if (theTutorial != null)
                        {
                            theList.Items.Add(theTutorial);
                        }
                        if (theLab != null)
                        {
                            theList.Items.Add(theLab);
                        }
                    
                }
            }
        }

        private bool IsCollide(ListBox theList,Course colidingCourse)
        {
            Course toCompare;
            for (int i = 0; i < theList.Items.Count; i++)
            {
                try
                {
                    toCompare = (Course)theList.Items[i];
                }
                catch (Exception)
                {
                    return false;
                }
                if (toCompare.IsSameClassName(colidingCourse))
                {
                    return true;
                }
            }
            return false;

        }

        private void RefreshGrid()
        {
            tgbs.Clear();
            Course toAdd=null;
            Course theTutorial=null;
            Course theLab = null;
            bool isCollide=false;
            //get the courses
            Course[] arrCourse = GlobalVariablesClass.courseSelected.ToArray();

            for (int i = 0; i < arrCourse.Length; i++)
            {
                try
                {
                    toAdd = arrCourse[i];
                    isCollide = tgbs.CheckCollision(toAdd);
                    if (!isCollide)
                    {
                        theTutorial = toAdd.GetTutorial();
                        if (theTutorial != null)
                        {
                            isCollide = tgbs.CheckCollision(theTutorial);
                        }
                        theLab = toAdd.GetLab();
                        if (theLab != null)
                        {
                            isCollide = tgbs.CheckCollision(theLab);
                        }
                        if (!isCollide)
                        {
                            tgbs.AddCourseToGrid(toAdd);
                            if (theLab != null)
                            {
                                tgbs.AddCourseToGrid(theLab);
                            }
                            if (theTutorial != null)
                            {
                                tgbs.AddCourseToGrid(theTutorial);
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    isCollide = false;
                }
                if (isCollide)
                {
                    ui_list_inGb_currCourses.Items.Remove(toAdd);
                    ui_list_inGb_currCourses.Items.Remove(theLab);
                    ui_list_inGb_currCourses.Items.Remove(theTutorial);
                    ui_list_inGb_courseMissing.Items.Add(theLab);
                    ui_list_inGb_courseMissing.Items.Add(theTutorial);
                    ui_list_inGb_courseMissing.Items.Add(toAdd);
                    ui_status_lbl.Text = "Could not add [" + toAdd.ToString() + "] :: Collision detected";
                    ui_status_lbl.ForeColor = Color.Red;
                }
            }

            if (showingConstraints)
            {
                tgbs.DisplayStudentConstraints(currentUser);
            }
        }

        private void ui_list_inGb_courseMissing_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void ui_tableLayout_DoubleClick(object sender, EventArgs e)
        {
            ShowBigGrid();

            //reset the hide link
            ui_link_inGb_edit_courses.Tag = 0;
            ui_link_inGb_edit_courses.Text = "Edit";
        }

        private void ShowBigGrid()
        {
            Font theFont = new Font(FontFamily.GenericSansSerif, 6);
            tgbs.ResetConstraintsUI();
            if (!isBig)
            {
                prevTableHeight = ui_tableLayout.Height;
                prevTableWidth = ui_tableLayout.Width;
                prevFormHeight = this.Height;
                prevFormWidth = this.Width;

                theFont = new Font(theFont, FontStyle.Bold);
                int theHeight = SystemInformation.PrimaryMonitorSize.Height;
                theHeight -= theHeight /= 4;
                this.Top = 10;
                this.AutoSize = true;
                SetCoursePanelVisibility(false);
                ui_tableLayout.Height = theHeight;
                ui_tableLayout.Width = ui_panel_courseDisplay.Left + (ui_panel_courseDisplay.Width);
                tgbs.ChangeFont(theFont);
                ui_lbl_largerView.Text = "Double click to see a smaller view";
                isBig = true;

                ui_panel_studentprofile.Visible = false;

               
            }
            else
            {
                ui_lbl_largerView.Text = "Double click to see a larger view";
                ui_tableLayout.Height = prevTableHeight;
                ui_tableLayout.Width = prevTableWidth;
                this.Height = prevFormHeight;
                this.Width = prevFormWidth;

                SetEditPanelVisibility(false);

                theFont = tableDefaultFont;
                tgbs.ChangeFont(theFont);
                isBig = false;
                
                if (tgbs.addingConstraints)
                {
                    tgbs.addingConstraints = false;
                    ui_status_lbl.Text = string.Empty;
                    ShowProfile(true);
                    tgbs.RefreshTtbGridColors();
                }
                ShowProfile(false);
            }
        }



        private void SetCoursePanelVisibility(bool isVisible)
        {
            ui_panel_courseDisplay.Visible = isVisible;
            if (isBig)
            {
                ui_panel_edit.Visible = isVisible;
            }
            else
            {
                SetEditPanelVisibility(false);
                ui_panel_edit.Visible = false;
            }
        }

        private void ui_panel_edit_Paint(object sender, PaintEventArgs e)
        {

        }

        private void ui_link_inGb_showAll_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            EducationalProgram ep = GlobalVariablesClass.session_loggedInStudent.GetProgram();

            if (ui_check_missing.Checked)
            {
                LoadProgramCourses(ep, GlobalVariablesClass.courseSelected, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
            }
            else
            {
                LoadProgramCourses(currentUser.GetProgram(), null, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
            }
        }

        private void ui_link_inGb_showMissing_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            EducationalProgram ep = GlobalVariablesClass.session_loggedInStudent.GetProgram();
            LoadProgramCourses(ep, GlobalVariablesClass.courseSelected, ui_check_Conflict.Checked, ui_check_showTimes.Checked);

        }

        private void saveCoursesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveSession();
            ui_status_lbl.Text = "Saved!";
            ui_status_lbl.ForeColor = Color.Green;
        }

        private void saveCoursesToolStripMenuItem1_Click(object sender, EventArgs e)
        {

        }

        private void ui_check_Conflict_CheckedChanged(object sender, EventArgs e)
        {
            if (ui_check_missing.Checked)
            {
                LoadProgramCourses(currentUser.GetProgram(), GlobalVariablesClass.courseSelected, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
            }
            else
            {
                LoadProgramCourses(currentUser.GetProgram(), null, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
            }
        }

        private void ui_check_missing_CheckedChanged(object sender, EventArgs e)
        {
            if (ui_check_missing.Checked)
            {
                LoadProgramCourses(currentUser.GetProgram(), GlobalVariablesClass.courseSelected, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
            }
            else
            {
                LoadProgramCourses(currentUser.GetProgram(), null, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
            }
        }

        private void ui_check_showTimes_CheckedChanged(object sender, EventArgs e)
        {
            ui_panel_generator.Visible = !ui_panel_generator.Visible;
            LoadStudentCourses(currentUser, ui_check_showTimes.Checked,false);

            if (ui_check_showTimes.Checked)
            {
                tgbs.GenerateStudentSchedule(GlobalVariablesClass.courseSelected);
            }
            else
            {
                tgbs.Clear();
            }

             if (ui_check_missing.Checked)
            {
                LoadProgramCourses(currentUser.GetProgram(), GlobalVariablesClass.courseSelected, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
                
            }
            else
            {
                LoadProgramCourses(currentUser.GetProgram(), null, ui_check_Conflict.Checked, ui_check_showTimes.Checked);
            }
        }

        private void ui_link_generateSch_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            generatedResult = GenerateCourse();
            resultCounter = 0;
            ui_lbl_generate_counter.Text = "1/" + generatedResult.Length;
            DisplayGeneratedSchedule(generatedResult[resultCounter]);

        }

        private void DisplayGeneratedSchedule(List<Course> toDisplay)
        {
            tgbs.Clear();
            tgbs.GenerateStudentSchedule(toDisplay);
        }


        private List<Course>[] GenerateCourse()
        {
            Course[] arrCourseSelected; // = new Course[ui_list_inGb_currCourses.Items.Count/2];
            List<Course>[] listCourseSections; // = new List<Course>[arrCourseSelected.Length];
            List<Course>[] toReturn;
            List<Course> coursesSelected = new List<Course>();
            EducationalProgram eduProg = currentUser.GetProgram();
            Course[] arrProgramCourse = eduProg.GetAllCourses().ToArray();
            Course temp1;
            Course temp2;

            for (int i = 0; i < ui_list_inGb_currCourses.Items.Count; i++)
            {
                if (!ui_list_inGb_currCourses.Items[i].ToString().Contains('T'))
                {
                    coursesSelected.Add((Course)ui_list_inGb_currCourses.Items[i]);
                }
            }

            arrCourseSelected = new Course[coursesSelected.Count];

            for (int i = 0; i < arrCourseSelected.Length; i++)
            {
                arrCourseSelected[i] = coursesSelected[i];
            }

            listCourseSections = new List<Course>[arrCourseSelected.Length];

            for (int i = 0; i < listCourseSections.Length; i++)
            {
                listCourseSections[i] = new List<Course>();

                temp1 = arrCourseSelected[i];
                if (!temp1.ToString().Contains('T'))
                {
                    for (int k = 0; k < arrProgramCourse.Length; k++)
                    {
                        temp2 = arrProgramCourse[k];                        
                        if (temp2.IsSameClassName(temp1))
                        {
                            listCourseSections[i].Add(temp2);
                        }
                    }
                }
            }

            toReturn = new List<Course>[6];

            for (int i = 0; i < toReturn.Length; i++)
            {
                toReturn[i] = new List<Course>();

                for (int k = 0; k < listCourseSections.Length; k++)
                {
                    try
                    {
                        toReturn[i].Add(listCourseSections[k][i]);
                    }
                    catch (Exception)
                    {
                        //out of bounds
                        toReturn[i] = new List<Course>();
                        break;
                    }
                }
                
            }
            List<List<Course>> finalReturn = new List<List<Course>>();
            bool isCollide = false;
            for (int i = 0; i < toReturn.Length; i++)
            {
                isCollide = false;
                tgbs.Clear();
                for (int k = 0; k < toReturn[i].Count; k++)
                {
                    isCollide = tgbs.CheckCollision(toReturn[i][k]);
                    if (isCollide)
                        break;
                    tgbs.AddCourseToGrid(toReturn[i][k]);
                }
                if (toReturn[i].Count == 0)
                {
                    isCollide = true;
                }
                if (!isCollide)
                {
                    finalReturn.Add(toReturn[i]);
                }

            }
            List<Course>[] finalFinalReturn = finalReturn.ToArray();
            return finalFinalReturn;

        }

        private List<Course> ToGenerate(List<Course> theList, Course baseCourse)
        {
            GeneratorList<Course> toRet = new GeneratorList<Course>();
                         
            Course toUse;
            List<Course> toRecurse;

            string toShow = string.Empty;

            if (theList.Count == 1)
            {
                return toRet;
            }
            else if (theList.Count == 0)
            {
                return toRet;
            }
            else
            {

                toRet = new GeneratorList<Course>();
                toUse = baseCourse;
                if (baseCourse != null && !toUse.GetCourseName().Equals(baseCourse.GetCourseName()))
                {
                    return toRet;
                }
                toRecurse = GetMissing(theList, toUse);
                toRecurse = RemoveCollisions(toRecurse, toUse);

                for (int k = 0; k < theList.Count; k++)
                {
                    toShow += theList[k];
                }

                toShow = string.Empty;
                for (int k = 0; k < toRecurse.Count; k++)
                {
                    toShow += toRecurse[k];
                }

                toRet.Add(toUse);
                if (toRecurse.Count == 0)
                {
                    return toRet;
                }
                if (toRecurse.Count == 1)
                {
                    return toRet;
                }
                toUse = toRecurse[0];
                toShow = string.Empty;

                toRet.Append(ToGenerate(toRecurse, toUse));
                GlobalVariablesClass.GeneratedCourses[cntr_sch] = toRet;
                return toRet;

            }
        }

        private List<Course> GetMissing(List<Course> theList, Course toRemove)
        {

            List<Course> toRet = new List<Course>();

            for (int i = 0; i < theList.Count; i++)
            {
                if (!theList[i].IsSameClassName(toRemove))
                {
                    toRet.Add(theList[i]);
                }
            }

            return toRet;
        }

        private List<Course> RemoveCollisions(List<Course> theList, Course toCollide)
        {
            List<Course> toRet = new List<Course>();
            tgbs.Clear();
            tgbs.AddCourseToGrid(toCollide);
            for (int i = 0; i < theList.Count; i++)
            {
                if (toCollide != theList[i] && !tgbs.CheckCollision(theList[i]))
                {
                    tgbs.AddCourseToGrid(theList[i]);
                    toRet.Add(theList[i]);
                }
            }

            return toRet;
        }
        private void GenerateSchedule()
        {
            //generates a list of schedules with classes selected

            string theCourseName;
            Course theCourse;

            List<Course>[] toGenerate = new List<Course>[ui_list_inGb_currCourses.Items.Count];
            Course[] arrEduCourse = GlobalVariablesClass.session_loggedInStudent.GetProgram().GetAllCourses().ToArray();
            //init
            for (int i = 0; i < toGenerate.Length; i++)
            {
                toGenerate[i] = new List<Course>();
            }

            for (int i = 0; i < toGenerate.Length; i++)
            {
                theCourse = (Course)ui_list_inGb_currCourses.Items[i];

                if (!theCourse.IsTutorialOrLab())
                {
                    theCourseName = theCourse.GetCourseName();
                    //get all the courses with that name in program
                    for (int k = 0; k < arrEduCourse.Length; k++)
                    {
                        if (theCourse.IsSameClassName(arrEduCourse[k]))
                        {
                            toGenerate[i].Add(arrEduCourse[k]);
                        }
                    }
                }
            }

            Course[] arrCourse;
            List<Course> selectedCourses = new List<Course>();


            for (int i = 0; i < toGenerate.Length; i++)
            {
                arrCourse = toGenerate[i].ToArray();
                for (int k = 0; k < arrCourse.Length; k++)
                {
                    selectedCourses.Add(arrCourse[k]);
                }
            }
        }

        private void viewMyInfoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (isBig)
            {
                ShowBigGrid();
            }
            ShowProfile(true);
        }

        private void ShowProfile(bool isVisible)
        {         
            ui_panel_courseDisplay.Visible = !isVisible;
            ui_panel_studentprofile.Visible = isVisible;
            SetEditPanelVisibility(false);

            if (!isVisible)
            {
                SetEditPanelVisibility(false);
                this.AutoSize = false;
                this.Width = GlobalVariablesClass.originalStudentPageWidth;
            }
        }

        private void ui_form_StudentPage_MouseDown(object sender, MouseEventArgs e)
        {

        }

        private void ui_form_StudentPage_MouseUp(object sender, MouseEventArgs e)
        {
            isFormDragged = false;
        }

        private void ui_timer_formDrag_Tick(object sender, EventArgs e)
        {
            if (isFormDragged)
            {
                Left = Cursor.Position.X - formMoveXOffset;
                Top = Cursor.Position.Y - formMoveYOffset;
            }
        }

        private void ui_toolStrip_top_MouseDown(object sender, MouseEventArgs e)
        {
            formMoveXOffset = e.X;
            formMoveYOffset = e.Y;
            isFormDragged = true;
        }

        private void ui_toolStrip_top_MouseUp(object sender, MouseEventArgs e)
        {
            isFormDragged = false;
        }

        private void ui_form_StudentPage_Move(object sender, EventArgs e)
        {

        }

        private void ui_link_changePw_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ui_lbl_pwChanged.Visible = false;
            ChangePassword();
        }

        private void ChangePassword()
        {
            SetPasswordPanelVisibility(true);

        }

        void SetPasswordPanelVisibility(bool isVisible)
        {
            ui_panel_pwChange.Visible = isVisible;

            ui_pwPanel_btn_change.Enabled = false;
            ui_pwPanel_btn_change.BackColor = Color.Gray;

            ui_pwPanel_txt_newPw.Text = string.Empty;
            ui_pwPanel_txt_oldPw.Text = string.Empty;

            ui_pwPanel_lbl_error.Visible = false;
            ui_pwPanel_lbl_error.Text = string.Empty;

            ui_pwPanel_lbl_error.AutoSize = true;

            if (isVisible)
            {
                ui_pwPanel_txt_oldPw.Focus();
            }
        }

        private void ui_pwPanel_txt_oldPw_TextChanged(object sender, EventArgs e)
        {
            if (ui_pwPanel_txt_oldPw.Text != string.Empty)
            {
                ui_pwPanel_lbl_oldPw.ForeColor = Color.Green;
            }
            else
            {
                ui_pwPanel_lbl_oldPw.ForeColor = Color.Red;
            }

            CheckButtonEnablePassword();
        }

        private void ui_pwPanel_txt_oldPw_Leave(object sender, EventArgs e)
        {
            if (ui_pwPanel_txt_oldPw.Text != string.Empty)
            {
                ui_pwPanel_lbl_oldPw.ForeColor = Color.Green;
            }
            else
            {
                ui_pwPanel_lbl_oldPw.ForeColor = Color.Red;
            }

            CheckButtonEnablePassword();
        }

        private void ui_pwPanel_txt_newPw_TextChanged(object sender, EventArgs e)
        {
            if (ui_pwPanel_txt_newPw.Text != string.Empty)
            {
                ui_pwPanel_lbl_newPw.ForeColor = Color.Green;
            }
            else
            {
                ui_pwPanel_lbl_newPw.ForeColor = Color.Red;
            }

            CheckButtonEnablePassword();
        }

        private void ui_pwPanel_txt_newPw_Leave(object sender, EventArgs e)
        {
            if (ui_pwPanel_txt_newPw.Text != string.Empty)
            {
                ui_pwPanel_lbl_newPw.ForeColor = Color.Green;
            }
            else
            {
                ui_pwPanel_lbl_newPw.ForeColor = Color.Red;
            }

            CheckButtonEnablePassword();
        }

        private void CheckButtonEnablePassword()
        {
            if (!ui_pwPanel_txt_newPw.Text.Equals(string.Empty) && !ui_pwPanel_txt_oldPw.Equals(string.Empty))
            {
                ui_pwPanel_btn_change.Enabled = true;
                ui_pwPanel_btn_change.BackColor = Color.LightGreen;
            }
            else
            {
                ui_pwPanel_btn_change.Enabled = false;
                ui_pwPanel_btn_change.BackColor = Color.Gray;
            }
        }

        private void ui_pwPanel_btn_change_Click(object sender, EventArgs e)
        {
            ChangeThePw();
        }

        private void ChangeThePw()
        {
            //disable
            ui_pwPanel_txt_oldPw.Enabled = false;
            ui_pwPanel_txt_newPw.Enabled = false;
            //validation
            string oldPw = ui_pwPanel_txt_oldPw.Text;
            string newPw = ui_pwPanel_txt_newPw.Text;
            long ID = currentUser.GetID();

            bool isError = false;
            bool isCap = false;
            bool isDigit = false;
            bool is6 = false;
            int theAScii = -1;

            //check if oldpw matches current pw
            bool oldPwMatch = currentUser.VerifyCredentials(ID, oldPw);

            ui_pwPanel_lbl_error.Visible = false;

            if (oldPwMatch)
            {
                //validate new pw with 6+ chars, 1 capital letter, 1 digit
                if (newPw.Length >= 6)
                {
                    is6 = true;
                    isError = true;
                }

                for (int i = 0; i < newPw.Length; i++)
                {
                    theAScii = (int)newPw[i];
                    if (theAScii > 64 && theAScii < 91)
                    {
                        isCap = true;
                    }
                    if (theAScii > 47 && theAScii < 58)
                    {
                        isDigit = true;
                    }
                }

                isError = !isDigit || !isCap || !is6;

                if (isError)
                {
                    ui_pwPanel_txt_oldPw.Enabled = true;
                    ui_pwPanel_txt_newPw.Enabled = true;

                    ui_pwPanel_lbl_error.Visible = true;
                    ui_pwPanel_lbl_error.Text = "New password must contain:\n6+ chars, 1+ capital, 1+ digit!";
                    ui_pwPanel_txt_newPw.Text = string.Empty;
                    ui_pwPanel_txt_oldPw.Text = string.Empty;

                    ui_pwPanel_txt_oldPw.Focus();
                }
                else
                {
                    ui_pwPanel_txt_oldPw.Enabled = true;
                    ui_pwPanel_txt_newPw.Enabled = true;
                    currentUser.ChangePassword(newPw);
                    ui_lbl_pwChanged.Visible = true;
                    ui_lbl_pwChanged.Text = "Changed!";
                    SetPasswordPanelVisibility(false);
                }
            }
            else
            {
                ui_pwPanel_txt_oldPw.Enabled = true;
                ui_pwPanel_txt_newPw.Enabled = true;

                ui_pwPanel_lbl_error.Visible = true;
                ui_pwPanel_lbl_error.Text = "Old password does not match!";

                ui_pwPanel_txt_newPw.Text = string.Empty;
                ui_pwPanel_txt_oldPw.Text = string.Empty;

                ui_pwPanel_txt_oldPw.Focus();
            }
        }

        private void ui_pwPanel_txt_newPw_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue == 13)
            {
                if (ui_pwPanel_btn_change.Enabled)
                {
                    ChangeThePw();
                }
            }
        }

        private void ui_link_constraints_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ShowConstraintUI(true);
            changeMade = true;
        }

        private void ShowConstraintUI(bool isVisible)
        {
            tgbs.addingConstraints = isVisible;
            tgbs.ui_st_toDisplay = ui_status_lbl;
            ui_status_lbl.Text = "Select date/time for your constraint";
            ShowBigGrid();
        }

        private void ui_form_StudentPage_FormClosed(object sender, FormClosedEventArgs e)
        {

        }

        private void ui_list_inGb_currCourses_Leave(object sender, EventArgs e)
        {
            if (prevTtbForColor != null)
            {
                prevTtbForColor.SetBlocColor(prevColor);
            }
        }

        private void ui_picture_leave_MouseEnter(object sender, EventArgs e)
        {
            ui_picture_leave.Image = Properties.Resources.back_arrowHigh;
        }

        private void ui_picture_leave_MouseLeave(object sender, EventArgs e)
        {
            ui_picture_leave.Image = Properties.Resources.back_arrow;
        }

        private void ui_picture_leave_Click(object sender, EventArgs e)
        {
            ShowProfile(false);
            SetEditPanelVisibility(false);
            this.AutoSize = false;
            this.Width = GlobalVariablesClass.originalStudentPageWidth;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            resultCounter++;
            if (resultCounter == generatedResult.Length)
            {
                resultCounter--;
            }
            ui_lbl_generate_counter.Text = (resultCounter+1) + "/" + (generatedResult.Length);
            DisplayGeneratedSchedule(generatedResult[resultCounter]);
            //frm.Show();
        }

        private void ui_pwPanel_link_hide_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            SetPasswordPanelVisibility(false);
        }

        private void ui_link_showConstraint_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (ui_link_showConstraint.Tag == null)
            {
                ui_link_showConstraint.Tag = 0;
            }
            if ((int)ui_link_showConstraint.Tag == 0)
            {
                showingConstraints = true;
                ui_link_showConstraint.Tag = 1;
                tgbs.DisplayStudentConstraints(currentUser);
                ui_link_showConstraint.Text = "Hide Constraints";
            }
            else
            {
                showingConstraints = false;
                ui_link_showConstraint.Tag = 0;
                ui_link_showConstraint.Text = "Show Constraints";
                tgbs.Clear();
                tgbs.GenerateStudentSchedule(GlobalVariablesClass.courseSelected);
                
            }
            
        }

        private void button1_Click(object sender, EventArgs e)
        {
            resultCounter--;
            if (resultCounter == -1)
            {
                resultCounter++;
            }
            ui_lbl_generate_counter.Text = (resultCounter+1) + "/" + (generatedResult.Length);
            DisplayGeneratedSchedule(generatedResult[resultCounter]);
        }
    }
}
